---
title: "Table"
description: "Tables are used to display tabular data using rows and columns. They allow users to quickly scan, sort, compare, and take action on large amounts of data."
---

import {tableContent} from "@/content/components/table";

# Table

Tables are used to display tabular data using rows and columns. They allow users to quickly scan, sort, compare, and take action on large amounts of data.

<ComponentLinks component="table" reactHook="useTable" />

---

<CarbonAd/>

## Installation

<PackageManagers
  showGlobalInstallWarning
  commands={{
    cli: "npx heroui-cli@latest add table",
    npm: "npm install @heroui/table",
    yarn: "yarn add @heroui/table",
    pnpm: "pnpm add @heroui/table",
    bun: "bun add @heroui/table"
  }}
/>


## Import

HeroUI exports 6 table-related components:

- **Table**: The main component to display a table.
- **TableHeader**: The header of the table.
- **TableBody**: The body of the table.
- **TableColumn**: The column of the table.
- **TableRow**: The row of the table.
- **TableCell**: The cell of the table.

<ImportTabs
  commands={{
    main: `import {
    Table,
    TableHeader,
    TableBody,
    TableColumn,
    TableRow,
    TableCell
} from "@heroui/react";`,
    individual: `import {
    Table,
    TableHeader,
    TableBody,
    TableColumn,
    TableRow,
    TableCell
} from "@heroui/table";`,
  }}
/>

## Usage

<CodeDemo title="Usage" files={tableContent.usage} />

### Dynamic

To render a table dynamically, you can use the `columns` prop to pass the columns and `items` prop to pass the data.

<CodeDemo title="Dynamic" files={tableContent.dynamic} />

#### Why not array map?

Using the `items` prop and providing a render function allows [react-aria](https://react-spectrum.adobe.com/react-aria/index.html)
to automatically cache the results of rendering each item and avoid re-rendering all items in the
collection when only one of them changes. This has big performance benefits for large
collections.

You could also use `Array.map` to render the items, but it will not be as performant as using the `items` and `columns` prop.

Example:

```jsx
import {Table, TableHeader, TableColumn, TableBody, TableRow, TableCell, getKeyValue} from "@heroui/react";

const rows = [...];

const columns = [...];

export default function App() {
  return (
    <Table aria-label="Example table with dynamic content">
      <TableHeader>
        {columns.map((column) =>
          <TableColumn key={column.key}>{column.label}</TableColumn>
        )}
      </TableHeader>
      <TableBody>
        {rows.map((row) =>
          <TableRow key={row.key}>
            {(columnKey) => <TableCell>{getKeyValue(row, columnKey)}</TableCell>}
          </TableRow>
        )}
      </TableBody>
    </Table>
  );
}
```

> **Note**: To learn more about React Aria collections and how to use them, please check [React Aria Collections](https://react-spectrum.adobe.com/react-stately/collections.html).

### Empty State

You can use the `emptyContent` prop to render a custom component when the table is empty.

<CodeDemo title="Empty State" highlightedLines="11" files={tableContent.empty} />

### Without Header

In case you don't want to render the header, you can use the `hideHeader` prop.

<CodeDemo title="Without Header" files={tableContent.withoutHeader} />

### Without Wrapper

By default the table is wrapped in a `div` element with a small shadow effect and a border radius.
You can use the `removeWrapper` prop to remove the wrapper and only render the table.
However, the `removeWrapper` prop has no effect on a virtualized table, as the wrapper is required to manage its height.

<CodeDemo title="Without Wrapper" files={tableContent.withoutWrapper} />

### Custom Cells

You can render any component inside the table cell. In the example below, we are rendering different components according to the `key` of the column.

<CodeDemo title="Custom Cells" files={tableContent.customCells} />

### Striped Rows

You can use the `isStriped` prop to render striped rows.

<CodeDemo title="Striped Rows" files={tableContent.striped} />

### Single Row Selection

It is possible to make the table rows selectable. To do so, you can use the `selectionMode` prop. Use `defaultSelectedKeys` to
provide a default set of selected rows.

<CodeDemo title="Single Row Selection" files={tableContent.singleSelection} />

> **Note**: The value of the selected keys must match the key prop of the row.

### Multiple Row Selection

You can also select multiple rows by using the `selectionMode="multiple"` prop. Use `defaultSelectedKeys` to
provide a default set of selected rows.

<CodeDemo title="Multiple Row Selection" files={tableContent.multipleSelection} />

> **Note**: When using multiple selection, selectable checkboxes will be rendered in the first column of the table.

### Disallow Empty Selection

Table also supports a `disallowEmptySelection` prop which forces the user to have at least one
row in the Table selected at all times. In this mode, if a single row is selected and the
user presses it, it will not be deselected.

<CodeDemo title="Disallow Empty Selection" files={tableContent.disallowEmptySelection} />

### Controlled Selection

To programmatically control row selection, use the `selectedKeys` prop paired with the `onSelectionChange` callback.
The key prop from the selected rows will be passed into the callback when the row is pressed, allowing you to update state accordingly.

<CodeDemo title="Controlled Selection" files={tableContent.controlledSelection} />

> **Note**: The `selectedKeys` property must be a `Set` object.

### Disabled Rows

You can disable rows by using the `disabledKeys` prop. This will prevent rows from being
selectable as shown in the example below.

<CodeDemo title="Disabled Rows" files={tableContent.disabledRows} />

### Selection Behavior

By default, Table uses the `toggle` selection behavior, which behaves like a checkbox group:
clicking, tapping, or pressing the <Kbd>Space</Kbd> or <Kbd>Enter</Kbd> keys toggles selection for the focused row.

When the `selectionBehavior` prop is set to `replace`, clicking a row with the mouse replaces
the selection with only that row. Using the arrow keys moves both focus and selection.
To select multiple rows, modifier keys such as <Kbd>Ctrl</Kbd>, <Kbd>Cmd</Kbd>, and <Kbd>Shift</Kbd> can be used.

<CodeDemo title="Selection Behavior" files={tableContent.selectionBehavior} />

### Rows Actions

Table supports rows via the `onRowAction` callback. In the default `toggle` selection
behavior, when nothing is selected, clicking or tapping the row triggers the row action.

This behavior is slightly different in the `replace` selection behavior, where single
clicking selects the row and actions are performed via double click.

<CodeDemo title="Rows Actions" files={tableContent.rowActions} />

### Sorting Rows

Table supports sorting its data when a column header is pressed. To designate that a `Column`
should support sorting, provide it with the `allowsSorting` prop.

Table accepts a `sortDescriptor` prop that defines the current column key to sort by
and the sort direction (ascending/descending). When the user presses a sortable column
header, the column's key and sort direction is passed into the `onSortChange` callback,
allowing you to update the `sortDescriptor` appropriately.

We recommend using the `useAsyncList` hook from [@react-stately/data](https://react-spectrum.adobe.com/react-stately/useAsyncList.html) to manage the data sorting. So make
sure to install it before using the sorting feature.

<PackageManagers
  commands={{
    npm: "npm install @react-stately/data",
    yarn: "yarn add @react-stately/data",
    pnpm: "pnpm add @react-stately/data",
    bun: "bun add @react-stately/data",
  }}
/>

```jsx
import {useAsyncList} from "@react-stately/data";
```

<Spacer y={2} />

<CodeDemo
  asIframe
  title="Sorting Rows"
  resizeEnabled={false}
  displayMode="visible"
  files={tableContent.sorting}
  previewHeight="520px"
  iframeSrc="/examples/table/sorting"
/>

> Note that we passed the `isLoading` and `loadingContent` props to `TableBody` to
> render a loading state while the data is being fetched.

### Sort Icon

You can override the default sort icon by specifying `sortIcon`. This prop is only applied when `allowsSorting` is `true`.

<CodeDemo
  asIframe
  title="Sort Icon"
  resizeEnabled={false}
  displayMode="visible"
  files={tableContent.sortIcon}
  previewHeight="520px"
  iframeSrc="/examples/table/sort-icon"
/>

### Loading more data

Table allows you to add a custom component at the end of the table, on the example below we are
using a button to load more data.

<CodeDemo
  asIframe
  title="Loading more data"
  resizeEnabled={false}
  displayMode="visible"
  files={tableContent.loadMore}
  highlightedLines="36-45"
  previewHeight="620px"
  iframeSrc="/examples/table/load-more"
/>

> **Note**: We passed the `isHeaderSticky` to the `Table` component to make the header sticky.

### Paginated Table

You can use the [Pagination](/components/pagination) component to paginate the table.

<CodeDemo title="Paginated Table" files={tableContent.paginated} />

### Async Pagination

It is also possible to use the [Pagination](/components/pagination) component to paginate the table asynchronously. To fetch the data, we are using the `useSWR` hook from [SWR](https://swr.vercel.app/docs/pagination).

<CodeDemo
  asIframe
  title="Async Paginated Table"
  resizeEnabled={false}
  files={tableContent.asyncPagination}
  previewHeight="600px"
  displayMode="visible"
  iframeSrc="/examples/table/async-pagination"
/>

### Infinite Pagination

Table also supports infinite pagination. To do so, you can use the `useAsyncList` hook from [@react-stately/data](https://react-spectrum.adobe.com/react-stately/useAsyncList.html) and
[@heroui/use-infinite-scroll](https://www.npmjs.com/package/@heroui/use-infinite-scroll) hook.

<PackageManagers
  commands={{
    npm: "npm install @react-stately/data @heroui/use-infinite-scroll",
    yarn: "yarn add @react-stately/data @heroui/use-infinite-scroll",
    pnpm: "pnpm add @react-stately/data @heroui/use-infinite-scroll",
    bun: "bun add @react-stately/data @heroui/use-infinite-scroll",
  }}
/>

```jsx
import { useInfiniteScroll } from "@heroui/use-infinite-scroll";
import { useAsyncList } from "@react-stately/data";
```

<Spacer y={2} />

<CodeDemo
  asIframe
  title="Infinite Paginated Table"
  resizeEnabled={false}
  files={tableContent.infinitePagination}
  previewHeight="620px"
  displayMode="visible"
  showPreview={true}
  showOpenInCodeSandbox={false}
  iframeSrc="/examples/table/infinite-pagination"
/>


### Virtualization

Table supports virtualization, which allows efficient rendering of large lists by only rendering items that are visible in the viewport. You can enable virtualization by setting the `isVirtualized` prop to `true`.

<CodeDemo
  title="Virtualization"
  files={tableContent.virtualization}
/>

> **Note**: The virtualization strategy is based on the [@tanstack/react-virtual](https://tanstack.com/virtual/latest) package, which provides efficient rendering of large lists by only rendering items that are visible in the viewport.

#### Ten Thousand Items

Here's an example of using virtualization with 10,000 items.

<CodeDemo title="Ten Thousand Items" files={tableContent.virtualizationTenThousand} />

#### Max Table Height

The `maxTableHeight` prop is used to set the maximum height of the table. This is required when using virtualization. By default, it's set to `600`.

<CodeDemo title="Max Table Height" files={tableContent.virtualizationCustomMaxTableHeight} />

#### Custom Row Height

The `rowHeight` prop is used to set the height of each row in the table. This is required when using virtualization. By default, it's set to `40`.

<CodeDemo title="Custom Row Height" files={tableContent.virtualizationCustomItemHeight} />

### Use Case Example

When creating a table, you usually need core functionalities like sorting, pagination, and filtering. In the
example below, we combined all these functionalities to create a complete table.

<CodeDemo
  asIframe
  typescriptStrict={true}
  title="Table use Case Example"
  resizeEnabled={false}
  files={tableContent.useCase}
  previewHeight="630px"
  displayMode="visible"
  iframeSrc="/examples/table/use-case"
/>

## Slots

- **base**: Defines a flexible column layout and relative positioning for the table component.
- **wrapper**: Applies to the outermost wrapper, providing padding, flexible layout, relative positioning, visual styles, and scrollable overflow handling.
- **table**: Sets the table to have a full minimum width and auto-adjusting height.
- **thead**: Specifies rounded corners for the first child row in the table header.
- **tbody**: No specific styles are applied to the body of the table.
- **tr**: Styles for table rows including group focus, outline properties, and a set of undefined focus-visible classes.
- **th**: Styles for table headers, including padding, text alignment, font properties, and special styles for sortable columns.
- **td**: Applies to table cells, with properties for padding, alignment, and relative positioning, plus special styles for first child elements, selection indication, and disabled cells.
- **tfoot**: No specific styles are applied to the footer of the table.
- **sortIcon**: Styles for sorting icons, with properties for margin, opacity, and transition effects based on sorting direction and hover state.
- **emptyWrapper**: Defines style for an empty table, with text alignment, color, and a specified height.
- **loadingWrapper**: Style applied when the table is loading, positioning it centrally in its container.

### Custom Styles

You can customize the `Table` component by passing custom Tailwind CSS classes to the component slots.

<CodeDemo
  asIframe
  title="Table custom styles example"
  resizeEnabled={false}
  files={tableContent.customStyles}
  previewHeight="540px"
  displayMode="visible"
  iframeSrc="/examples/table/custom-styles"
/>

<Spacer y={4} />

## Data Attributes

`TableBody` has the following attributes:

- **data-empty**:
  When the table is empty.
- **data-loading**:
  When the table data is loading. Based on `TableBody` `isLoading` and `loadingContent` props.

`TableRow` has the following attributes:

- **data-selected**:
  When the row is selected. Based on `Table` `selectedKeys` prop.
- **data-disabled**:
  When the row is disabled. Based on `Table` `disabledKeys` prop.
- **data-hover**:
  When the row is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)
- **data-focus-visible**:
  When the row is being focused with the keyboard. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-first**:
  When the row is the first row.
- **data-middle**:
  When the row is in the middle.
- **data-odd**:
  When the row is odd.
- **data-last**:
  When the row is the last row.

`TableCell` has the following attributes:

- **data-selected**:
  When the cell row is selected. Based on `Table` `selectedKeys` prop.
- **data-focus-visible**:
  When the cell is being focused with the keyboard. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).

<Spacer y={4} />

## Accessibility

- Exposed to assistive technology as a grid using ARIA.
- Keyboard navigation between columns, rows, cells, and in-cell focusable elements via the arrow keys.
- Single, multiple, or no row selection via mouse, touch, or keyboard interactions.
- Support for disabled rows, which cannot be selected.
- Column sorting support.
- Async loading, infinite scrolling, filtering, and sorting support.
- Support for both toggle and replace selection behaviors.
- Labeling support for accessibility.
- Ensures that selections are announced using an ARIA live region.
- Support for marking columns as row headers, which will be read when navigating the rows with a screen reader.
- Optional support for checkboxes in each row for selection, as well as in the header to select all rows.
- Automatic scrolling support during keyboard navigation.
- Support for row actions via double click, Enter key, or tapping.
- Typeahead to allow focusing rows by typing text.
- Long press to enter selection mode on touch when there is both selection and row actions.

<Spacer y={4} />

## API

### Table Props

<APITable
  data={[
    {
      attribute: "children*",
      type: "ReactNode[]",
      description: "The elements that make up the table. Includes the TableHeader, TableBody, TableColumn, and TableRow.",
      default: "-"
    },
    {
      attribute: "color",
      type: "default | primary | secondary | success | warning | danger",
      description: "Color of the selected rows, and checkboxes.",
      default: "default"
    },
    {
      attribute: "layout",
      type: "auto | fixed",
      description: "Defines the layout of the table.",
      default: "auto"
    },
    {
      attribute: "radius",
      type: "none | sm | md | lg",
      description: "The border-radius of the table.",
      default: "lg"
    },
    {
      attribute: "shadow",
      type: "none | sm | md | lg",
      description: "The shadow size of the table.",
      default: "sm"
    },
        {
      attribute: "maxTableHeight",
      type: "number",
      description: "The maximum height of the table in pixels. Required when using virtualization.",
      default: 600
    },
    {
      attribute: "rowHeight",
      type: "number", 
      description: "The fixed height of each row item in pixels. Required when using virtualization.",
      default: 40
    },
    {
      attribute: "isVirtualized",
      type: "boolean",
      description: "Whether to enable virtualization. By default, it's enabled when the number of items exceeds 50.",
      default: "undefined"
    },
    {
      attribute: "hideHeader",
      type: "boolean",
      description: "Whether to hide the table header.",
      default: "false"
    },
    {
      attribute: "isStriped",
      type: "boolean",
      description: "Whether to apply striped rows in the table.",
      default: "false"
    },
    {
      attribute: "isCompact",
      type: "boolean", 
      description: "Whether to apply compact style to the table.",
      default: "false"
    },
    {
      attribute: "isHeaderSticky",
      type: "boolean",
      description: "Whether to make the table header sticky.",
      default: "false"
    },
    {
      attribute: "fullWidth",
      type: "boolean",
      description: "Whether to make the table full width.",
      default: "true"
    },
    {
      attribute: "removeWrapper",
      type: "boolean",
      description: "Whether the base container should not be rendered for a non-virtualized table.",
      default: "false"
    },
    {
      attribute: "BaseComponent",
      type: "React.ComponentType<any>",
      description: "A custom wrapper component for the table.",
      default: "div"
    },
    {
      attribute: "topContent",
      type: "ReactNode",
      description: "Provides content to include a component in the top of the table.",
      default: "-"
    },
    {
      attribute: "bottomContent",
      type: "ReactNode", 
      description: "Provides content to include a component in the bottom of the table.",
      default: "-"
    },
    {
      attribute: "topContentPlacement",
      type: "inside | outside",
      description: "Where to place the topContent component.",
      default: "inside"
    },
    {
      attribute: "bottomContentPlacement",
      type: "inside | outside",
      description: "Where to place the bottomContent component.",
      default: "inside"
    },
    {
      attribute: "showSelectionCheckboxes",
      type: "boolean",
      description: "Whether the row selection checkboxes should be displayed.",
      default: "-"
    },
    {
      attribute: "sortDescriptor",
      type: "SortDescriptor",
      description: "The current sorted column and direction.",
      default: "-"
    },
    {
      attribute: "selectedKeys",
      type: "Selection",
      description: "The currently selected keys in the collection (controlled).",
      default: "-"
    },
    {
      attribute: "defaultSelectedKeys",
      type: "Selection",
      description: "The initial selected keys in the collection (uncontrolled).",
      default: "-"
    },
    {
      attribute: "disabledKeys",
      type: "Selection",
      description: "A set of keys for rows that are disabled.",
      default: "-"
    },
    {
      attribute: "disallowEmptySelection",
      type: "boolean",
      description: "Whether the collection allows empty selection.",
      default: "-"
    },
    {
      attribute: "selectionMode",
      type: "single | multiple | none",
      description: "The type of selection that is allowed in the collection.",
      default: "none"
    },
    {
      attribute: "selectionBehavior",
      type: "toggle | replace",
      description: "How multiple selection should behave in the collection.",
      default: "toggle"
    },
    {
      attribute: "disabledBehavior",
      type: "selection | all",
      description: "Whether disabledKeys applies to all interactions, or only selection.",
      default: "selection"
    },
    {
      attribute: "allowDuplicateSelectionEvents",
      type: "boolean",
      description: "Whether onSelectionChange should fire even if the new set of keys is the same as the last.",
      default: "-"
    },
    {
      attribute: "disableAnimation",
      type: "boolean",
      description: "Whether to disable the table and checkbox animations.",
      default: "false"
    },
    {
      attribute: "checkboxesProps",
      type: "CheckboxProps",
      description: "Props to be passed to the checkboxes.",
      default: "-"
    },
    {
      attribute: "classNames",
      type: "Partial<Record<'base' | 'table' | 'thead' | 'tbody' | 'tfoot' | 'emptyWrapper' | 'loadingWrapper' | 'wrapper' | 'tr' | 'th' | 'td' | 'sortIcon', string>>",
      description: "Allows to set custom class names for the dropdown item slots.",
      default: "-"
    },
    {
      attribute: "isKeyboardNavigationDisabled",
      type: "boolean",
      description: "Whether to disable keyboard navigations or not.",
      default: "false"
    }
  ]}
/>

### Table Events

<APITable
  data={[
    {
      attribute: "onRowAction",
      type: "(key: React.Key) => void",
      description: "Handler that is called when a user performs an action on the row.",
      default: "-"
    },
    {
      attribute: "onCellAction",
      type: "(key: React.Key) => void",
      description: "Handler that is called when a user performs an action on the cell.",
      default: "-"
    },
    {
      attribute: "onSelectionChange",
      type: "(keys: Selection) => any",
      description: "Handler that is called when the selection changes.",
      default: "-"
    },
    {
      attribute: "onSortChange",
      type: "(descriptor: SortDescriptor) => any",
      description: "Handler that is called when the sorted column or direction changes.",
      default: "-"
    }
  ]}
/>

### TableHeader Props

<APITable
  data={[
    {
      attribute: "children*",
      type: "ReactNode[]",
      description: "A list of Column(s) or a function. If the latter, a list of columns must be provided using the columns prop",
      default: "-"
    },
    {
      attribute: "columns",
      type: "T[]",
      description: "A list of table columns.",
      default: "-"
    }
  ]}
/>

### TableColumn Props

<APITable
  data={[
    {
      attribute: "children*",
      type: "ReactNode",
      description: "Static child columns or content to render as the column header",
      default: "-"
    },
    {
      attribute: "align",
      type: "start | center | end",
      description: "The alignment of the column's contents relative to its allotted width",
      default: "start"
    },
    {
      attribute: "hideHeader",
      type: "boolean",
      description: "Whether the column should hide its header text",
      default: "false"
    },
    {
      attribute: "allowsSorting",
      type: "boolean",
      description: "Whether the column allows sorting",
      default: "-"
    },
    {
      attribute: "sortIcon",
      type: "ReactNode",
      description: "Overrides the default sort icon. Only applied when `allowsSorting` is `true`",
      default: "-"
    },
    {
      attribute: "isRowHeader",
      type: "boolean",
      description: "Whether a column is a row header and should be announced by assistive technology during row navigation",
      default: "-"
    },
    {
      attribute: "textValue",
      type: "string",
      description: "A string representation of the column's contents, used for accessibility announcements",
      default: "-"
    },
    {
      attribute: "width",
      type: "string | number",
      description: "The width of the column",
      default: "-"
    },
    {
      attribute: "minWidth",
      type: "string | number",
      description: "The minimum width of the column",
      default: "-"
    },
    {
      attribute: "maxWidth",
      type: "string | number",
      description: "The maximum width of the column",
      default: "-"
    }
  ]}
/>

### TableBody Props

<APITable
  data={[
    {
      attribute: "children*",
      type: "RowElement | RowElement[] | ((item: T) => RowElement)",
      description: "The contents of the table body. Supports static items or a function for dynamic rendering",
      default: "-"
    },
    {
      attribute: "items",
      type: "Iterable<T>",
      description: "A list of row objects in the table body used when dynamically rendering rows",
      default: "-"
    },
    {
      attribute: "isLoading",
      type: "boolean",
      description: "Whether the table body is loading.",
      default: "-"
    },
    {
      attribute: "loadingState",
      type: "LoadingState",
      description: "Handler that is called when more items should be loaded, e.g. while scrolling near the bottom",
      default: "-"
    },
    {
      attribute: "loadingContent",
      type: "ReactNode",
      description: "Content to display while loading more items",
      default: "-"
    },
    {
      attribute: "emptyContent",
      type: "ReactNode",
      description: "Content to display when there are no items in the table body",
      default: "-"
    }
  ]}
/>

### TableBody Events

<APITable
  data={[
    {
      attribute: "onLoadMore",
      type: "() => any",
      description: "A list of row objects in the table body used when dynamically rendering rows",
      default: "-"
    }
  ]}
/>

### TableRow Props

<APITable
  data={[
    {
      attribute: "children*",
      type: "CellElement | CellElement[] | CellRenderer",
      description: "Rendered contents of the row or row child items",
      default: "-"
    },
    {
      attribute: "textValue",
      type: "string",
      description: "A string representation of the row's contents, used for features like typeahead",
      default: "-"
    }
  ]}
/>

### TableCell Props

<APITable
  data={[
    {
      attribute: "children*",
      type: "ReactNode",
      description: "The contents of the cell",
      default: "-"
    },
    {
      attribute: "textValue",
      type: "string",
      description: "A string representation of the row's contents, used for features like typeahead",
      default: "-"
    }
  ]}
/>

---

<Spacer y={2} />

### Table types

#### Sort descriptor

```ts
type SortDescriptor = {
  column: React.Key;
  direction: "ascending" | "descending";
};
```

#### Selection

```ts
type Selection = "all" | Set<React.Key>;
```

#### Loading state

```ts
type LoadingState = "loading" | "sorting" | "loadingMore" | "error" | "idle" | "filtering";
```
